import { createVNode, ref, Ref } from "vue";
import { BasicFormOptions } from "../basic-form-box/type";
import { TableOptions } from "../basic-table-box/type";
import { BasicFormBox } from "../basic-form-box/basic-form-box";
import { BasicTaleBox } from "../basic-table-box";
import { Page } from "../page";
import { DATA_QUERY_DETAILS_FORM_METHOD, repaintProxy, TABLE_BOX_METHOD } from "..";
import { Find, FromsType, LayoutOption, RequestOptions, TablesType } from "./types";
import { ReqPageData } from "./static-source";
import DataQueryDetailLayoutVue from "./data-query-detail-layout.vue";

export type LifeOption = {
	mounted?: () => void;
	beforeUnmount?: () => void;
};
type PageType = { page: number; pageSize: number };
export abstract class DataQueryDetailPage<
	FN extends Record<string, unknown>,
	TN extends Record<string, unknown>
> extends Page {
	private forms = {} as FromsType<FN, keyof FN>;
	private tables = {} as TablesType<TN, keyof TN>;
	private workflow = {};
	private layoutList: LayoutOption<keyof (FN & TN)>[] = [];
	private lifeOption!: LifeOption;
	private reqOpt!: RequestOptions<TN[any]>;
	name: string = "";

	constructor(name: string, lifeOption: LifeOption = {}, private dialogLayout: boolean = false) {
		super(name);
		this.lifeOption = lifeOption;
		// 初始化
		if (name) this.name = name;
		else throw new Error(`请设置页面的名字:name,当前的name值为：${name}`);
	}

	/** 初始化一个form */
	protected initForm<K extends keyof FN>(name: K, opt: Partial<BasicFormOptions<FN[K]>> = {}) {
		if (this.forms[name]) throw Error(`${String(name)}已存在, 请修改!`);

		const agentForm = repaintProxy(
			new BasicFormBox<FN[K]>({ options: [], ...opt }),
			key => DATA_QUERY_DETAILS_FORM_METHOD.includes(key),
			() => this.repaint()
		);
		this.forms[name] = agentForm as unknown as BasicFormBox<FN[keyof FN]>;
		/** 设置布局信息 */
		this.layoutList.push({ name, sort: 1, block: null, title: "" });
		return agentForm;
	}

	/** 初始化一个table */
	protected initTable<K extends keyof TN>(
		name: K,
		/** 请求信息配置 */
		reqOpt: RequestOptions<TN[K]> = {},
		/** 表格信息配置 */
		opt: Partial<TableOptions<TN[K]>> = {}
	) {
		/** 校验 */
		if (this.tables[name]) throw Error(`${String(name)}已存在, 请修改!`);
		/** 构造 table */
		const table = new BasicTaleBox<TN[K]>();
		const {
			url,
			formParam = reqOpt.formParam || true,
			headerTyps,
			method = reqOpt.method || "GET",
			resultField = reqOpt.resultField || "rows",
			mergeParams = reqOpt.mergeParams || true,
			filterData,
			filterSearchData,
			otherCodeReplace,
		} = reqOpt;
		/** 创建请求 */
		const req = (() => {
			if (url) {
				const request = new ReqPageData<TN[K]>(
					table,
					url!,
					resultField,
					headerTyps,
					method,
					mergeParams,
					filterData,
					filterSearchData,
					otherCodeReplace
				);
				table.setRequest(
					(pageConfig: PageType, url?: string, params?: Record<string, any>) => {
						request
							.requestPageData(
								pageConfig,
								() => params || this.getFormVal("all"),
								url
							)
							.then(() => this.repaint());
					}
				);
				return request;
			}
		})();

		table.setTableOption({
			...opt,
			changePage: (pageConfig: { page: number; pageSize: number }) => {
				if (req) {
					const getParam = formParam ? () => this.getFormVal("all") : () => ({});
					req.requestPageData(pageConfig, getParam).then(() => {
						table.setPageConfig(pageConfig);
						this.repaint();
					});
				}
			},
		});
		/** 创建表格代理 */
		const agentTable = repaintProxy(
			table,
			key => TABLE_BOX_METHOD.includes(key),
			() => this.repaint()
		);
		/** 缓存表格 */
		this.tables[name] = agentTable as unknown as BasicTaleBox<TN[keyof TN]>;
		/** 设置布局信息 */
		this.layoutList.push({ name, sort: 1, block: null, title: "" });
		return agentTable;
	}

	/** 获取表单实例 */
	getForm<K extends keyof FN>(name: K) {
		return this.forms[name] as BasicFormBox<Find<FN, K>>;
	}
	/** 获取表格实例 */
	getTable<K extends keyof TN>(name: K) {
		return this.tables[name] as BasicTaleBox<Find<TN, K>>;
	}

	/** 获取表单值 */
	getFormVal<K extends keyof FN>(name: K | "all") {
		let obj: Record<string, FN[keyof FN]> = {};
		if (name === "all") {
			Object.entries(this.forms).forEach(([key, curr]) => (obj[key] = curr.getFormValue()));
			return obj;
		}

		const target = this.getForm(name);
		return target?.getFormValue() || {};
	}
	/** 获取表格值 */
	getTableVal<K extends keyof TN>(name: K | "all") {
		let obj: Record<string, TN[keyof TN][]> = {};
		if (name === "all") {
			Object.entries(this.tables).forEach(
				([key, curr]) => (obj[key] = curr.getTableSource())
			);
			return obj;
		}

		const target = this.getTable(name);
		return target.getTableSource() || [];
	}

	/** 设置配置 */
	setLifeOption(lifeOption: LifeOption) {
		this.lifeOption = lifeOption;
	}

	/** 设置布局 */
	setLayout(layoutList: LayoutOption<keyof (FN & TN)>[]) {
		layoutList = layoutList.map(lay => {
			let tar = this.layoutList.find(el => lay.name === el.name);
			if (!tar) throw new Error(`${lay.name as string} 没有被注册！！！`);
			tar = { ...tar, ...lay };
			return tar;
		});
		this.layoutList = layoutList;
		this.repaint();
	}

	getLayout() {
		return createVNode(DataQueryDetailLayoutVue, {
			forms: this.forms,
			tables: this.tables,
			layoutList: this.layoutList,
			workflow: this.workflow,
			dialogLayout: this.dialogLayout,
			onVnodeMounted: () => {
				this.lifeOption?.mounted?.call(null);
			},
			onVnodeBeforeUnmount: () => {
				this.lifeOption?.beforeUnmount?.call(null);
			},
		});
	}

	getVNode() {
		return this.createPageComponent();
	}
	setReqOpt(opt: RequestOptions<TN[any]>) {
		this.reqOpt = opt;
	}
	getReqOpt() {
		return this.reqOpt;
	}
}
